import {Module, MutationTree, ActionTree} from 'vuex';
import {RouteRecordRaw} from 'vue-router';
import store, {IRootState} from '../index';
import {asyncRoutes} from '../../router/index';
import {MenuData} from './menu';
import path from 'path';

// 定义state类型
export interface IPermissionState {
  routes: Array<RouteRecordRaw>;
  accessRoutes: Array<RouteRecordRaw>;
}

// 定义state
const state: IPermissionState = {
  routes: [],
  accessRoutes: []
}

// 定义mutation
const mutations: MutationTree<IPermissionState> = {
  SET_ROUTES(state, data: Array<RouteRecordRaw>) {
    state.routes = data
  },
  SET_ACCESS_ROUTES(state, data: Array<RouteRecordRaw>) {
    state.accessRoutes = data
  }
}

// 定义actions
const actions: ActionTree<IPermissionState, IRootState> = {
  generateRoutes({dispatch},type?: number) {
    return new Promise((resolve, reject) => {
      let accessedRoutes: Array<RouteRecordRaw> = []

      // 超级管理员角色, 拥有全部权限
      if (store.getters.roleNames.includes('super_admin')) {
        accessedRoutes = asyncRoutes;
        dispatch('menu/getAllMenuListByAdmin',null, {root: true})
        resolve(accessedRoutes)

      // 根据角色过滤菜单
      } else {
        const roles = store.getters.roleIds
        dispatch('menu/getAccessByRoles', roles, {root: true}) //此时就会更新侧边栏
          .then(menus => {
            if(type !== 1){ // 只有src/permission.ts里 动态注册路由时才会需要在这里对路由进行筛选 // 拖拽排序触发的generateRoutes动作则不需要对此进行筛选
              accessedRoutes = filterAsyncRoutes(menus, asyncRoutes)
              resolve(accessedRoutes)
            }
          })
          .catch(reject)
      }
    });
  }
}

// 定义user module
const permission: Module<IPermissionState, IRootState> = {
  namespaced: true,
  state,
  mutations,
  actions
}

export default permission

const filterAsyncRoutes = (menus: Array<MenuData>, routes: Array<RouteRecordRaw> /*asyncRoutes*/) => {
  // 生成要匹配的路由path数组
  const routePaths = generateRoutePaths(menus)
  // 生成匹配path的路由表
  const routerList = generateRoutes(routes /*asyncRoutes*/, routePaths)
  return routerList
}
// 生成路由路径数组
const generateRoutePaths = (menus: Array<MenuData>): string[] => {
  return menus.map(menu => menu.path)
}
// 白名单
const whiteList = ['/:pathMatch(.*)*']
// 生成可访问路由表
const generateRoutes = (routes: Array<RouteRecordRaw> /*第一次是router/index.ts里的 asyncRoutes*/, routePaths: string[], basePath = '/') => {
  const routerData: Array<RouteRecordRaw> = []

  //第一次是router/index.ts里的 asyncRoutes
  routes.forEach(route => {
    const routePath = path.resolve(basePath, route.path);  //vue-router的子路由路径是相对路径

    if (route.children) { // 先看子路由 是否有匹配上的路由
      route.children = generateRoutes(route.children, routePaths, routePath);
    }

    // 如果当前路由子路由数量大于0（说明） 或 paths中包含当面路由path 就需要把当前父路由添加上
    if (
      routePaths.includes(routePath) //只有一级的路由 或则是 子路由
      || (route.children && route.children.length >= 1) //比如用户有 `/system/user权限` 但没有给 `/system权限`, 这里就会自动把 `/system权限`给带上
      || whiteList.includes(routePath)
    ) {
      routerData.push(route)
    }
  })
  return routerData
}
